package com.share.order.service.impl;

import cn.hutool.core.util.RandomUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.share.common.core.domain.R;
import com.share.common.security.utils.SecurityUtils;
import com.share.order.api.domain.*;
import com.share.order.mapper.OrderBillMapper;
import com.share.order.mapper.OrderInfoMapper;
import com.share.order.service.IOrderInfoService;
import com.share.rule.api.RemoteFeeRuleService;
import com.share.rule.api.domain.FeeRule;
import com.share.rule.api.domain.FeeRuleRequestForm;
import com.share.rule.api.domain.FeeRuleResponseVo;
import com.share.user.api.RemoteUserService;
import com.share.user.api.domain.UserInfo;
import org.joda.time.DateTime;
import org.joda.time.Minutes;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;

/**
 * 订单Service业务层处理
 *
 * @author atguigu
 * @date 2024-02-22
 */
@Service
public class OrderInfoServiceImpl extends ServiceImpl<OrderInfoMapper, OrderInfo> implements IOrderInfoService {

    @Autowired
    private RemoteFeeRuleService remoteFeeRuleService;

    @Autowired
    private RemoteUserService remoteUserInfoService;

    @Autowired
    private OrderBillMapper orderBillMapper;

    @Override
    public OrderInfo getByOrderNo(String orderNo) {
        return baseMapper.selectOne(
                new LambdaQueryWrapper<OrderInfo>()
                        .eq(OrderInfo::getOrderNo, orderNo)
        );
    }

    @Override
    public OrderInfo getNoFinishOrder(Long userId) {
        // 查询用户是否有使用中与未支付订单
        return baseMapper.selectOne(
                new LambdaQueryWrapper<OrderInfo>()
                        .eq(OrderInfo::getUserId, userId)
                        // 订单状态：0:充电中 1：未支付 2：已支付
                        .in(OrderInfo::getStatus, Arrays.asList("0", "1"))
                        .orderByDesc(OrderInfo::getId)
                        .last("limit 1")
        );
    }

    @Override
    public void processPaySuccess(String orderNo) {
        OrderInfo orderInfo = baseMapper.selectOne(
                new LambdaQueryWrapper<OrderInfo>()
                        .eq(OrderInfo::getOrderNo, orderNo)
        );
        if ("1".equals(orderInfo.getStatus())) {
            orderInfo.setStatus("2");
            orderInfo.setPayTime(new Date());
        }
        baseMapper.updateById(orderInfo);
    }

    @Override
    public Long saveOrder(SubmitOrderVo submitOrderVo) {
        OrderInfo orderInfo = new OrderInfo();
        //设置需要数据
        orderInfo.setUserId(submitOrderVo.getUserId());
        orderInfo.setOrderNo(RandomUtil.randomString(8));
        orderInfo.setPowerBankNo(submitOrderVo.getPowerBankNo());
        orderInfo.setStartTime(new Date());
        orderInfo.setStartStationId(submitOrderVo.getStartStationId());
        orderInfo.setStartStationName(submitOrderVo.getStartStationName());
        orderInfo.setStartCabinetNo(submitOrderVo.getStartCabinetNo());
        // 费用规则
        FeeRule feeRule = remoteFeeRuleService.detailFeeRule(submitOrderVo.getFeeRuleId()).getData();
        orderInfo.setFeeRuleId(submitOrderVo.getFeeRuleId());
        orderInfo.setFeeRule(feeRule.getDescription());
        orderInfo.setStatus("0");
        orderInfo.setCreateTime(new Date());
        orderInfo.setCreateBy(SecurityUtils.getUsername());
        // 用户相关信息，需要继续增加
//        UserInfo userInfo = remoteUserInfoService.getInfo(orderInfo.getUserId()).getData();
//        orderInfo.setUserInfoVo();
        baseMapper.insert(orderInfo);
        return orderInfo.getId();
    }

    /**
     * 业务逻辑：
     * 1. 查询订单是否存在，不存在直接返回（不存在可能是管理员维护），存在继续处理
     * 2. 获取充电时长，使用规则引擎Drools计算费用
     * 3. 将费用分为免费部分与收费部分保存到数据库
     *
     * @param endOrderVo 结束订单参数
     */
    @Override
    public void endOrder(EndOrderVo endOrderVo) {
        // 根据充电宝编号 + 订单状态（充电中）查询订单信息
        OrderInfo orderInfo = baseMapper.selectOne(
                new LambdaQueryWrapper<OrderInfo>()
                        .eq(OrderInfo::getPowerBankNo, endOrderVo.getPowerBankNo())
                        .eq(OrderInfo::getStatus, "0")
        );
        // 如果不存在订单，直接返回
        if (orderInfo == null) {
            throw new RuntimeException("订单不存在");
        }
        // 订单存在则结束订单（更新订单相关数据）
        orderInfo.setEndTime(endOrderVo.getEndTime());
        orderInfo.setEndStationId(endOrderVo.getEndStationId());
        orderInfo.setEndStationName(endOrderVo.getEndStationName());
        orderInfo.setEndCabinetNo(endOrderVo.getEndCabinetNo());
        // 包含充电时长 以分钟单位
        Date startTime = orderInfo.getStartTime();
        Date endTime = orderInfo.getEndTime();
        // 使用joda工具获取充电时长，单位分钟
        int duration = Minutes.minutesBetween(new DateTime(startTime), new DateTime(endTime)).getMinutes();
        orderInfo.setDuration(duration);
        // 规则引擎进行费用计算（远程调用）
        FeeRuleRequestForm feeRuleRequestForm = new FeeRuleRequestForm();
        feeRuleRequestForm.setDuration(duration);
        feeRuleRequestForm.setFeeRuleId(orderInfo.getFeeRuleId());
        FeeRuleResponseVo feeRuleResponseVo = remoteFeeRuleService.calculateOrderFee(feeRuleRequestForm).getData();
        // 更新费用
        orderInfo.setTotalAmount(feeRuleResponseVo.getTotalAmount());
        orderInfo.setDeductAmount(new BigDecimal("0"));
        orderInfo.setRealAmount(feeRuleResponseVo.getTotalAmount());
        if (orderInfo.getRealAmount().subtract(new BigDecimal(0)).doubleValue() == 0) {
            orderInfo.setStatus("2");
        } else {
            orderInfo.setStatus("1");
        }
        baseMapper.updateById(orderInfo);
        // 数据库新增免费账单数据
        OrderBill freeOrderBill = new OrderBill();
        freeOrderBill.setOrderId(orderInfo.getId());
        freeOrderBill.setBillItem(feeRuleResponseVo.getFreeDescription());
        freeOrderBill.setBillAmount(new BigDecimal(0));
        orderBillMapper.insert(freeOrderBill);
        // 数据库新增收费账单数据（如果有超过免费时间账单数据）
        BigDecimal exceedPrice = feeRuleResponseVo.getExceedPrice();
        if (exceedPrice.doubleValue() > 0) {
            OrderBill exceedOrderBill = new OrderBill();
            exceedOrderBill.setOrderId(orderInfo.getId());
            exceedOrderBill.setBillItem(feeRuleResponseVo.getExceedDescription());
            exceedOrderBill.setBillAmount(feeRuleResponseVo.getExceedPrice());
            orderBillMapper.insert(exceedOrderBill);
        }
    }

    @Override
    public Map<String, Object> getOrderCount(String sql) {
        //调用mapper方法执行sql语句
        List<Map<String, Object>> list = baseMapper.getOrderCount(sql);
        Map<String, Object> dataMap = new HashMap<>(2);
        List<Object> dateList = new ArrayList<>();
        List<Object> countList = new ArrayList<>();
        //把list集合遍历，得到每个map
        for (Map<String, Object> map : list) {
            //把每个map里面日期得到放到新的list集合里面
            dateList.add(map.get("order_date"));
            //把每个map里面数量得到放到新的list集合里面
            countList.add(map.get("order_count"));
        }
        //把两个list集合放到dataMap中，返回
        dataMap.put("dateList", dateList);
        dataMap.put("countList", countList);
        return dataMap;
    }

    @Override
    public List<OrderInfo> selectOrderListByUserId(Long userId) {
        // 根据用户id查询用户所有订单列表，返回list集合
        List<OrderInfo> list = baseMapper.selectList(
                new LambdaQueryWrapper<OrderInfo>()
                        .eq(OrderInfo::getUserId, userId)
                        .orderByDesc(OrderInfo::getId)
        );
        // 遍历list集合，得到每个orderInfo对象
        for (OrderInfo orderInfo : list) {
            // 判断订单状态是0（充电中），实时计算充电时间和金额
            if ("0".equals(orderInfo.getStatus())) {
                // 计算当前充电时间（当前时间 - 开始时间 = 充电时间）
                int minutes = Minutes.minutesBetween(new DateTime(orderInfo.getStartTime()), new DateTime()).getMinutes();
                // 如果充电时长大于0
                if (minutes > 0) {
                    orderInfo.setDuration(minutes);
                    FeeRuleRequestForm feeRuleRequestForm = new FeeRuleRequestForm();
                    feeRuleRequestForm.setDuration(minutes);
                    feeRuleRequestForm.setFeeRuleId(orderInfo.getFeeRuleId());
                    FeeRuleResponseVo responseVo = remoteFeeRuleService.calculateOrderFee(feeRuleRequestForm).getData();
                    // 设置到orderInfo里面
                    orderInfo.setTotalAmount(responseVo.getTotalAmount());
                    orderInfo.setDeductAmount(new BigDecimal(0));
                    orderInfo.setRealAmount(responseVo.getTotalAmount());
                } else {
                    orderInfo.setDuration(0);
                    orderInfo.setTotalAmount(new BigDecimal(0));
                    orderInfo.setDeductAmount(new BigDecimal(0));
                    orderInfo.setRealAmount(new BigDecimal(0));
                }
            } else if ("1".equals(orderInfo.getStatus()) || "2".equals(orderInfo.getStatus())) {
                // 计算当前充电时间（结束时间 - 开始时间 = 充电时间）
                int minutes = Minutes.minutesBetween(
                        new DateTime(orderInfo.getStartTime()),
                        new DateTime(orderInfo.getEndTime())
                ).getMinutes();
                // 如果充电时长大于0
                if (minutes > 0) {
                    orderInfo.setDuration(minutes);
                    FeeRuleRequestForm feeRuleRequestForm = new FeeRuleRequestForm();
                    feeRuleRequestForm.setDuration(minutes);
                    feeRuleRequestForm.setFeeRuleId(orderInfo.getFeeRuleId());
                    FeeRuleResponseVo responseVo = remoteFeeRuleService.calculateOrderFee(feeRuleRequestForm).getData();
                    // 设置到orderInfo里面
                    orderInfo.setTotalAmount(responseVo.getTotalAmount());
                    orderInfo.setDeductAmount(new BigDecimal(0));
                    orderInfo.setRealAmount(responseVo.getTotalAmount());
                } else {
                    orderInfo.setDuration(0);
                    orderInfo.setTotalAmount(new BigDecimal(0));
                    orderInfo.setDeductAmount(new BigDecimal(0));
                    orderInfo.setRealAmount(new BigDecimal(0));
                }
            }
            List<OrderBill> orderBillList = orderBillMapper.selectList(
                    new LambdaQueryWrapper<OrderBill>()
                            .eq(OrderBill::getOrderId, orderInfo.getId())
            );
            orderInfo.setOrderBillList(orderBillList);
            UserInfo userInfo = remoteUserInfoService.getInfo(orderInfo.getUserId()).getData();
            UserInfoVo userInfoVo = new UserInfoVo();
            BeanUtils.copyProperties(userInfo, userInfoVo);
            orderInfo.setUserInfoVo(userInfoVo);
        }
        return list;
    }

    @Override
    public OrderInfo selectOrderInfoById(Long id) {
        // 根据id查询订单信息
        OrderInfo orderInfo = baseMapper.selectById(id);
        // 判断订单状态充电中 0
        if ("0".equals(orderInfo.getStatus())) {
            // 计算充电时间
            int minutes = Minutes.minutesBetween(new DateTime(orderInfo.getStartTime()), new DateTime()).getMinutes();
            // 充电时间大于0
            if (minutes > 0) {
                orderInfo.setDuration(minutes);
                FeeRuleRequestForm feeRuleRequestForm = new FeeRuleRequestForm();
                feeRuleRequestForm.setDuration(minutes);
                feeRuleRequestForm.setFeeRuleId(orderInfo.getFeeRuleId());
                FeeRuleResponseVo responseVo = remoteFeeRuleService.calculateOrderFee(feeRuleRequestForm).getData();
                // 设置到orderInfo里面
                orderInfo.setTotalAmount(responseVo.getTotalAmount());
                orderInfo.setDeductAmount(new BigDecimal(0));
                orderInfo.setRealAmount(responseVo.getTotalAmount());
            } else {
                orderInfo.setDuration(0);
                orderInfo.setTotalAmount(new BigDecimal(0));
                orderInfo.setDeductAmount(new BigDecimal(0));
                orderInfo.setRealAmount(new BigDecimal(0));
            }
        } else if ("1".equals(orderInfo.getStatus()) || "2".equals(orderInfo.getStatus())) {
            // 计算当前充电时间（结束时间 - 开始时间 = 充电时间）
            int minutes = Minutes.minutesBetween(
                    new DateTime(orderInfo.getStartTime()),
                    new DateTime(orderInfo.getEndTime())
            ).getMinutes();
            // 如果充电时长大于0
            if (minutes > 0) {
                orderInfo.setDuration(minutes);
                FeeRuleRequestForm feeRuleRequestForm = new FeeRuleRequestForm();
                feeRuleRequestForm.setDuration(minutes);
                feeRuleRequestForm.setFeeRuleId(orderInfo.getFeeRuleId());
                FeeRuleResponseVo responseVo = remoteFeeRuleService.calculateOrderFee(feeRuleRequestForm).getData();
                // 设置到orderInfo里面
                orderInfo.setTotalAmount(responseVo.getTotalAmount());
                orderInfo.setDeductAmount(new BigDecimal(0));
                orderInfo.setRealAmount(responseVo.getTotalAmount());
            } else {
                orderInfo.setDuration(0);
                orderInfo.setTotalAmount(new BigDecimal(0));
                orderInfo.setDeductAmount(new BigDecimal(0));
                orderInfo.setRealAmount(new BigDecimal(0));
            }
        }
        //OrderBill
        List<OrderBill> orderBillList = orderBillMapper.selectList(
                new LambdaQueryWrapper<OrderBill>()
                        .eq(OrderBill::getOrderId, id)
        );
        orderInfo.setOrderBillList(orderBillList);
        UserInfo userInfo = remoteUserInfoService.getInfo(orderInfo.getUserId()).getData();
        UserInfoVo userInfoVo = new UserInfoVo();
        BeanUtils.copyProperties(userInfo, userInfoVo);
        orderInfo.setUserInfoVo(userInfoVo);
        //返回对象
        return orderInfo;
    }

    public static void main(String[] args) {
        // 假设这是从JSON解析得到的List<Map<String, Object>>
        List<Map<String, Object>> dataList = new ArrayList<>();
        Map<String, Object> map1 = new HashMap<>();
        map1.put("MONTH", "2024-10");
        map1.put("order_count", 1);
        dataList.add(map1);

        Map<String, Object> map2 = new HashMap<>();
        map2.put("MONTH", "2024-11");
        map2.put("order_count", 4);
        dataList.add(map2);

        Map<String, Object> map3 = new HashMap<>();
        map3.put("MONTH", "2024-12");
        map3.put("order_count", 1);
        dataList.add(map3);

        Map dataMap = new HashMap<>();

        List<Object> monthList = new ArrayList<>();
        List<Object> orderCountList = new ArrayList<>();

        for (Map<String, Object> map : dataList) {
            monthList.add(map.get("MONTH"));
            orderCountList.add(map.get("order_count"));
        }

        dataMap.put("dateList", monthList);
        dataMap.put("countList", orderCountList);

    }
}
